// netlib_base.h

#ifndef _KS_INC_NETLIB_BASE_H_
#define _KS_INC_NETLIB_BASE_H_

#ifdef _WIN32
	#include <winsock2.h>
	#include <windows.h>
	#include <mswsock.h>
#else
	#include <sys/socket.h>
	#include <sys/epoll.h>
	#include <arpa/inet.h>
	#include <memory.h>
	#include <stdlib.h>
	#include <unistd.h>
#endif

#include "types.h"

KS_DECLS_BEGIN

#ifdef _WIN32
	typedef SOCKET						KSSockFD;
	typedef int							socklen_t;
	#define ks_sock_errno()				WSAGetLastError()
	#define ks_sock_close(fd)			closesocket(fd)

#else
	typedef int	KSSockFD;
	#define INVALID_SOCKET			-1
	#define ks_sock_errno()			errno
	#define ks_sock_close(fd)		close(fd)

#endif

// net environ init
//  1. init socket system
//  2. check system if support max_fd_num in linux
//
BOOL ks_net_environ_init(int max_fd_num);
void ks_net_environ_final(void);

// socket utils functions
// 
#define ks_sock_is_valid(fd)		((fd)!=INVALID_SOCKET)
#define ks_sock_is_invalid(fd)		((fd)==INVALID_SOCKET)

#define ks_sock_getsockopt(fd, sol, opt, val, len)		getsockopt((fd), (sol), (opt), (char*)(val), (len))
#define ks_sock_setsockopt(fd, sol, opt, val, len)		setsockopt((fd), (sol), (opt), (char*)(val), (len))

int		ks_sock_getsockname(struct sockaddr* addr, KSSockFD fd);
int		ks_sock_getpeername(struct sockaddr* addr, KSSockFD fd);

int		ks_sock_set_blocking(KSSockFD fd, BOOL block);
int		ks_sock_set_tcp_nodelay(KSSockFD fd, BOOL nodelay);
int		ks_sock_set_linger(KSSockFD fd, BOOL on, uint16_t time_second);
int		ks_sock_set_sndbuf(KSSockFD fd, int len);
int		ks_sock_set_rcvbuf(KSSockFD fd, int len);

// utils
// uint32_t ks_socket_getpeermac(KSSockFD fd);

// TCP address
BOOL	ks_net_address_parse(char saddr[32], const struct sockaddr* addr);
BOOL	ks_net_address_make(struct sockaddr* addr, const char* ip_port);
BOOL	ks_net_address_make_ip_port(struct sockaddr* addr, const char* ip, uint16_t port);
void	ks_net_address_make_ipv4(struct sockaddr* addr, uint32_t ip, uint16_t port);

// simple async socket
// 
typedef struct {
	KSSockFD	fd;

	BOOL		connected;
	int			err;
	uint32_t	connect_timeout;
	uint32_t	connect_start;

	size_t		rlen;
	char*		rbuf;
	char*		rpos;

	size_t		slen;
	char*		sbuf;
	char*		spos;
} KSSocket;

BOOL	ks_socket_connect(KSSocket* self, const struct sockaddr* addr, uint32_t connect_timeout_second);
void	ks_socket_close(KSSocket* self);
void	ks_socket_update(KSSocket* self);

KS_DECLS_END

#endif//_KS_INC_NETLIB_H_

